home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-12-16 | 14.1 KB | 600 lines | [TEXT/CWIE] |
- // ==================================================
- // myMime.c
- // Copyright (C) 1996 Mizutori Tetsuya, August 20, 1996, October 7, 1996.
- // ==================================================
- // This document is pretty-printed in 10-point Geneva font.
-
- #include "myMime.h"
-
- #ifdef DEBUG
- // This debug routine requires a dialog resource of 'DITL' and 'ALRT' whose ID is 1000.
- #define kAlertID 1000
- #define kNilFilterProc nil
- void SignalMsg( const unsigned char *p, const unsigned long pLen, Str255 msg );
- void SignalMsg( const unsigned char *p, const unsigned long pLen, Str255 msg )
- {
- short item;
- Str31 errNumbStr;
- Str255 str;
-
- str[0] = pLen;
- BlockMoveData(p,&str[1],str[0]);
-
- NumToString( pLen, errNumbStr );
-
- ParamText( errNumbStr, msg, str, "\p" );
-
- item = NoteAlert( kAlertID, kNilFilterProc );
- if ( item == cancel ) ExitToShell();
- }
- #endif // DEBUG
-
-
- // constants and global variables
- const unsigned char kPadChar = '=';
-
- const unsigned char kMimeBeginMark[] = "=?";
- const unsigned long kMimeBeginMarkLen = 2;
- const unsigned char kMimeEndMark[] = "?=";
- const unsigned long kMimeEndMarkLen = 2;
- const unsigned char kMimeSeparator[] = "?";
- const unsigned long kMimeSeparatorLen = 1;
- const unsigned char kCharSetName[] = "iso-2022-jp";
- const unsigned long kCharSetNameLen = 11;
- const unsigned char kEncodingName[] = "B";
- const unsigned long kEncodingNameLen = 1;
-
-
- // --------------------------------------------------
- // • CalcMimeEncodeLength
- // --------------------------------------------------
- // Mime separators and deliminators
-
- #ifdef MIME_ENCODE
- static unsigned long
- CalcMimeEncodeLength(
- unsigned long textSize )
- {
- unsigned long theSize;
-
- theSize = ( (textSize - 1)/3 + 1) * 4; /* Body */
-
- theSize += kMimeBeginMarkLen + kCharSetNameLen + kMimeSeparatorLen +
- kEncodingNameLen + kMimeSeparatorLen + /* Body + */ kMimeEndMarkLen;
-
- return theSize;
- }
- #endif // MIME_ENCODE
-
-
- // ==================================================
- // Mime encoding
- // ==================================================
-
- #ifdef MIME_ENCODE
-
- #ifdef MIME_ENCODE
- static const unsigned char Base64[ 64+4 ] =
- "ABCDEFGHIJKLMNOP"
- "QRSTUVWXYZabcdef"
- "ghijklmnopqrstuv"
- "wxyz0123456789+/"
- ;
- #endif // MIME_ENCODE
-
-
- // --------------------------------------------------
- // • MimeEncode
- // --------------------------------------------------
-
- void
- MimeEncode(
- Handle textH,
- unsigned long * textSizeP )
- {
- unsigned long textSize = *textSizeP;
- unsigned long newSize = CalcMimeEncodeLength( textSize );
-
- // Add extra spaces to 'textH', which enables to store the resulted text.
- SetHandleSize( textH, newSize );
- if ( MemError() != noErr ) return;
-
- {
- unsigned char * textP = (unsigned char *) *textH;
- BlockMoveData( textP, textP+(newSize-textSize), textSize );
-
- // HLock( textH );
- MimeEncodeText( textP+(newSize-textSize), textSize, textP, &newSize );
- // HUnlock( textH );
- }
-
- // Resize the resulted 'textH'.
- *textSizeP = newSize;
- SetHandleSize( textH, newSize );
- }
- #endif // MIME_ENCODE
-
-
- #ifdef MIME_ENCODE
- // --------------------------------------------------
- // • MimeEncodeJIS
- // --------------------------------------------------
-
- const unsigned char kEscKanjiIn[] = "\033$";
- const unsigned long kEscKanjiInLen = 2;
- const unsigned char kEscKanjiOut[] = "\033(";
- const unsigned long kEscKanjiOutLen = 2;
- const unsigned char kEscKanjiInx[] = "B@";
- const unsigned long kEscKanjiInxLen = 2;
- const unsigned char kEscKanjiOutx[] = "JBH";
- const unsigned long kEscKanjiOutxLen = 3;
-
- void
- MimeEncodeJIS(
- Handle textH,
- unsigned long * textSize )
- {
- unsigned long theSize;
- Handle theHndl;
-
- unsigned char * p = (unsigned char *) *textH;
- unsigned char * pEnd = p+ *textSize;
-
- unsigned char * pLast = p;
- unsigned char * pKanjiStart = nil;
-
- unsigned long len;
-
- HLock( textH );
-
- theSize = 0;
- theHndl = NewHandleClear( theSize );
- if ( MemError() != noErr ) return;
-
- while ( p < pEnd ) {
-
- if ( IsSameString(p,kEscKanjiInLen,kEscKanjiIn,kEscKanjiInLen) &&
- FindToken( kEscKanjiInx, kEscKanjiInxLen, p+kEscKanjiInLen, 1, &len ) ) {
-
- pKanjiStart = p;
- p += kEscKanjiInLen + 1;
-
- } else
- if ( IsSameString(p,kEscKanjiOutLen,kEscKanjiOut,kEscKanjiOutLen) &&
- FindToken( kEscKanjiOutx, kEscKanjiOutxLen, p+kEscKanjiOutLen, 1, &len ) &&
- pKanjiStart != nil ) {
-
- // Copy [pLast,pKanjiStart-1] -> q+
- TextAppend( theHndl, &theSize, pLast, pKanjiStart );
- {
- // MimiCode [pKanjiStart+3,p-1] -> q+
- unsigned char * theBodyStart = pKanjiStart;
- unsigned long theBodySize = p - theBodyStart + kEscKanjiOutLen + 1;
- unsigned long theMimeSize = CalcMimeEncodeLength(theBodySize);
- unsigned char * theMimeP = (unsigned char *) NewPtrClear( theMimeSize );
- MimeEncodeText( theBodyStart, theBodySize, theMimeP, &theMimeSize );
- TextAppend( theHndl, &theSize, theMimeP, theMimeP+theMimeSize );
- }
- // p += 3; // pLast = p; // pKanjiStart = nil;
- p += kEscKanjiOutLen + 1;
- pLast = p;
- pKanjiStart = nil;
-
- } else {
-
- p++;
-
- }
- }
-
- // Copy [pLast,pEnd-1] -> q+
- TextAppend( theHndl, &theSize, pLast, pEnd );
-
- HUnlock( textH );
-
- {
- unsigned char * theTextP = (unsigned char *) *theHndl;
- HLock( theHndl );
- *textSize = 0;
- TextAppend( textH, textSize, theTextP, theTextP+theSize );
- HUnlock( theHndl );
- }
-
- out:
- DisposeHandle( theHndl );
- }
- #endif // MIME_ENCODE
-
-
- #ifdef MIME_ENCODE
- // --------------------------------------------------
- // • MimeEncodeText
- // --------------------------------------------------
-
- unsigned long
- MimeEncodeText(
- const unsigned char * pStart,
- const unsigned long pLen,
- unsigned char * qStart,
- unsigned long * qLen )
- {
- unsigned char * q = qStart;
-
- BlockMoveData( kMimeBeginMark, q, kMimeBeginMarkLen );
- q += kMimeBeginMarkLen;
- BlockMoveData( kCharSetName, q, kCharSetNameLen );
- q += kCharSetNameLen;
- BlockMoveData( kMimeSeparator, q, kMimeSeparatorLen );
- q += kMimeSeparatorLen;
- BlockMoveData( kEncodingName, q, kEncodingNameLen );
- q += kMimeSeparatorLen;
- BlockMoveData( kMimeSeparator, q, kMimeSeparatorLen );
- q += kMimeSeparatorLen;
-
- {
- unsigned long len;
- Base64EncodeBody( pStart, pLen, q, &len );
- q += len;
- }
-
- BlockMoveData( kMimeEndMark, q, kMimeEndMarkLen );
- q += kMimeEndMarkLen;
-
- *qLen = (unsigned long) ( q - qStart );
-
- return pLen;
- }
- #endif // MIME_ENCODE
-
-
- #ifdef MIME_ENCODE
- // --------------------------------------------------
- // • Base64EncodeBody
- // --------------------------------------------------
-
- static void
- Base64EncodeBody(
- const unsigned char * p,
- const unsigned long pLen,
- unsigned char * q,
- unsigned long * qLen )
- {
- const unsigned char * pEnd = p + pLen;
- unsigned char * qStart = q;
-
- unsigned char s[4];
- unsigned long i, n;
- while ( p < pEnd ) {
- i = 0;
- while ( i < 3 && p < pEnd ) s[i++] = *p++;
- Base64Encode324( s, i, q, &n );
- q += n;
- }
-
- *qLen = (unsigned long) (q - qStart);
- }
- #endif // MIME_ENCODE
-
-
- #ifdef MIME_ENCODE
- // --------------------------------------------------
- // • Base64Encode324
- // --------------------------------------------------
-
- static void
- Base64Encode324(
- const unsigned char * p3,
- const unsigned long pLen, // in: pLen = [1,2,3]
- unsigned char * q4,
- unsigned long * qLen ) // out: qLen = 4
- {
- long i;
- long n = 0;
- BlockMoveData( p3, (unsigned char *) &n, pLen );
-
- for ( /*long*/ i=0; i<=pLen; i++ ) {
- unsigned char c = (n>>(26-6*i)) & 0x3F;
- q4[i] = Base64[ c ];
- }
-
- for ( /*long*/ i=pLen+1; i<4; i++ )
- q4[i] = kPadChar;
-
- *qLen = 4;
- }
- #endif // MIME_ENCODE
-
-
- // ==================================================
- // Mime decoding
- // ==================================================
-
- #ifdef MIME_DECODE
- static const unsigned char Esab64[ 128 ] = {
- // 0x00-0x1F
- 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
- // !"#$%&'()*+,-./
- 0,0,0,0,0,0,0,0, 0,0,0,62,0,0,0,63,
- // 0123456789:;<=>?
- 52,53,54,55,56,57,58,59, 60,61,0,0,0,0,0,0,
- // @A-O
- 0,0,1,2,3,4,5,6, 7,8,9,10,11,12,13,14,
- // P-Z[\]^_
- 15,16,17,18,19,20,21,22, 23,24,25,0,0,0,0,0,
- // `a-o
- 0,26,27,28,29,30,31,32, 33,34,35,36,37,38,39,40,
- // p-z{|}~\0
- 41,42,43,44,45,46,47,48, 49,50,51,0,0,0,0,0,
- };
- #endif // MIME_DECODE
-
-
- #ifdef MIME_DECODE
- // --------------------------------------------------
- // • MimeDecode
- // --------------------------------------------------
-
- void
- MimeDecode(
- Handle textH,
- unsigned long * textSize )
- {
- unsigned char * pStart = (unsigned char *) *textH;
- unsigned char * pEnd = pStart + *textSize;
- unsigned char * p = pStart;
- unsigned char * q = pStart;
- unsigned long qLen;
-
- while ( p < pEnd ) {
-
- unsigned long len;
- if ( *p == kMimeBeginMark[0] &&
- ( len = MimeDecodeText( p, (unsigned long) (pEnd - p), q, &qLen ) ) > 0 ) {
- p += len;
- q += qLen;
- } else {
- *q++ = *p++;
- }
- }
-
- // Resize the 'textH'.
- *textSize = (unsigned long) ( q - pStart );
- SetHandleSize( textH, *textSize );
- // ThrowIfOSErr_( ::MemError() );
- }
- #endif // MIME_DECODE
-
-
- #ifdef MIME_DECODE
- // --------------------------------------------------
- // • MimeDecodeText
- // --------------------------------------------------
- // p[] = "=?iso-2022-jp?B?xxxxxxxx?=AAAAAA..."
- // ->
- // p[return] = "AAAAAA..."
- // q[] = "yyyyyy"
-
- unsigned long
- MimeDecodeText(
- const unsigned char * pStart,
- const unsigned long pLen,
- unsigned char * qStart,
- unsigned long * qLen )
- {
- const unsigned char * pEnd = pStart + pLen;
- const unsigned char * p = pStart;
- unsigned char * q = qStart;
- unsigned long len;
-
- *qLen = 0;
-
- // The text must begin with 'kMimeBeginMark'.
- if ( ! FindToken( p, (pEnd-p), kMimeBeginMark, kMimeBeginMarkLen, &len ) ||
- len != 0 ) return 0;
- p += kMimeBeginMarkLen;
-
- // Check 'kCharSetName'.
- if ( ! FindToken( p, (pEnd-p), kMimeSeparator, kMimeSeparatorLen, &len ) ||
- ! IsSameString( p, len, kCharSetName, kCharSetNameLen ) ) return 0;
- p += len + kMimeSeparatorLen;
-
- // Check 'kEncodingName'.
- if ( ! FindToken( p, (pEnd-p), kMimeSeparator, kMimeSeparatorLen, &len ) ||
- ! IsSameString( p, len, kEncodingName, kEncodingNameLen ) ) return 0;
- p += len + kMimeSeparatorLen;
-
- // Pick up the encoded body.
- {
- const unsigned char * theEncodeBodyP = p;
- unsigned long theEncodeBodyLen;
- if ( ! FindToken( p, (pEnd-p), kMimeEndMark, kMimeEndMarkLen, &theEncodeBodyLen ) ) return 0;
- p += theEncodeBodyLen + kMimeEndMarkLen;
-
- Base64DecodeBody( theEncodeBodyP, theEncodeBodyLen, q, &len );
- *qLen += len;
- }
-
- return (unsigned long) (p - pStart);
- }
- #endif // MIME_DECODE
-
-
- #ifdef MIME_DECODE
- // --------------------------------------------------
- // • Base64DecodeBody
- // --------------------------------------------------
-
- static void
- Base64DecodeBody(
- const unsigned char * p,
- const unsigned long pLen,
- unsigned char * q,
- unsigned long * qLen )
- {
- const unsigned char * pEnd = p + pLen;
- unsigned char * qStart = q;
-
- unsigned char s[4];
- unsigned long i, n;
- while ( p < pEnd ) {
- i = 0;
- while ( i < 4 && p < pEnd ) {
- while ( p < pEnd ) {
- if ( IsCharBase64( *p ) ) { s[i++] = *p++; break; }
- ++p;
- }
- }
- Base64Decode423( s, i, q, &n );
- q += n;
- }
-
- *qLen = (unsigned long) (q - qStart);
- }
- #endif // MIME_DECODE
-
- #ifdef MIME_DECODE
- // --------------------------------------------------
- // • Base64Decode423
- // --------------------------------------------------
-
- static void
- Base64Decode423(
- const unsigned char * p4,
- const unsigned long pLen, // in: pLen = 4
- unsigned char * q3,
- unsigned long * qLen ) // out: qLen = [1,2,3]
- {
- long i;
- long n = 0;
- long k = 3;
-
- for ( /*long*/ i=0; i<4; i++ ) {
- unsigned char c = ( i < pLen ? p4[i] : kPadChar );
- n = (n<<6) + Esab64[ c & 0x7F ];
- if ( c == kPadChar ) k--;
- }
- n <<= 8;
-
- BlockMoveData( (unsigned char *) &n, q3, k );
- *qLen = k;
- }
- #endif // MIME_DECODE
-
-
- // ==================================================
- // Common functions
- // ==================================================
-
- static const unsigned char xlat[128] =
- // 0x00-0x1F
- "\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017"
- "\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
- " !\"#$%&'()*+,-./"
- "0123456789:;<=>?"
- "@ABCDEFGHIJKLMNO"
- "PQRSTUVWXYZ[\\]^_"
- "`ABCDEFGHIJKLMNO" // Replacing "`abcdefghijklmno".
- "PQRSTUVWXYZ{|}~" // Replacing "pqrstuvwxyz{|}~\0".
- ;
-
- // --------------------------------------------------
- // • IsCharBase64
- // --------------------------------------------------
-
- static Boolean
- IsCharBase64(
- unsigned char theChar )
- {
- if ( 'A' <= theChar && theChar <= 'Z' ) return true;
- if ( 'a' <= theChar && theChar <= 'z' ) return true;
- if ( '0' <= theChar && theChar <= '9' ) return true;
- if ( theChar == '+' ) return true;
- if ( theChar == '/' ) return true;
- if ( theChar == kPadChar ) return true;
-
- return false;
- }
-
-
- // --------------------------------------------------
- // • FindToken
- // --------------------------------------------------
-
- static Boolean
- FindToken(
- const unsigned char * pStart,
- const unsigned long pLen,
- const unsigned char * token,
- const unsigned long tokenLen,
- unsigned long * index )
- {
- unsigned long i = 0;
- unsigned char c = xlat[ token[0] & 0x7F ];
-
- while ( i < pLen ) {
- if ( ( xlat[ pStart[i] & 0x7F ] == c ) && ( i+tokenLen <= pLen ) &&
- IsSameString( &pStart[i], tokenLen, token, tokenLen ) ) {
- *index = i;
- return true;
- }
- i++;
- }
-
- *index = 0;
- return false;
- }
-
-
- // --------------------------------------------------
- // • IsSameString
- // --------------------------------------------------
-
- static Boolean
- IsSameString(
- const unsigned char * strA,
- const unsigned long strALen,
- const unsigned char * strB,
- const unsigned long strBLen )
- {
- unsigned long i = 0;
-
- while ( i<strALen && i<strBLen ) {
- if ( xlat[ strA[i] & 0x7F ] != xlat[ strB[i] & 0x7F ] ) return false;
- i++;
- }
-
- return ( strALen == strBLen );
- }
-
-
- #ifdef MIME_ENCODE
- // --------------------------------------------------
- // • TextAppend
- // --------------------------------------------------
-
- static unsigned long
- TextAppend(
- Handle textH,
- unsigned long * textSize,
- unsigned char * pStart,
- unsigned char * pEnd )
- {
- unsigned long theLen = (unsigned long) ( pEnd - pStart );
- unsigned long theSize = *textSize;
-
- if ( theLen == 0 ) goto out;
-
- SetHandleSize( textH, theSize+theLen );
- if ( MemError() != noErr ) goto out;
-
- BlockMoveData( pStart, ((unsigned char *) *textH)+theSize, theLen );
- *textSize = theSize+theLen;
-
- out:
- return theLen;
- }
- #endif // MIME_ENCODE
-
- // end of program
-